#ifndef __HVC_H__
#define __HVC_H__

#include "shyper_service.h"
#include "vmm.h"

#define MRS(var, reg) asm volatile("mrs %0, " #reg "\n\r" : "=r"(var))
#define MSR(reg, var) asm volatile("msr " #reg ", %0\n\r" ::"r"(var))

#define PAR_MASK (0x0000FFFFFFFFF000)
#define HVC_MODE(fid, event) (((fid << 8) | event) & 0xffff)

enum hvc_fid {
    HVC_SYS = 0,
    HVC_VMM,
    HVC_IVC,
    HVC_MEDIATED,
    HVC_SECURITY,
    HVC_CONFIG = 0x11,
    HVC_UNILIB = 0x12,
    HVC_SHMEM = 0x13,
};

enum ioctl_fid {
    IOCTL_SYS = 0x10,
};

enum hvc_sys_event {
    HVC_SYS_REBOOT = 0,
    HVC_SYS_SHUTDOWN,
    HVC_SYS_UPDATE = 3,
    HVC_SYS_TEST = 4,
};

enum hvc_vmm_event {
    HVC_VMM_LIST_VM = 0,
    HVC_VMM_GET_VM_STATE,
    HVC_VMM_BOOT_VM,
    HVC_VMM_SHUTDOWN_VM,
    HVC_VMM_REBOOT_VM,
    HVC_VMM_GET_VM_DEF_CFG,
    HVC_VMM_GET_VM_CFG,
    HVC_VMM_SET_VM_CFG,
    HVC_VMM_GET_VM_ID,
    HVC_VMM_TRACE_VMEXIT,
    HVC_VMM_MIGRATE_START,
    HVC_VMM_MIGRATE_READY,
    HVC_VMM_MIGRATE_MEMCPY,
    HVC_VMM_MIGRATE_FINISH,
    HVC_VMM_MIGRATE_INIT_VM,
    HVC_VMM_MIGRATE_VM_BOOT,
    HVC_VMM_VM_REMOVE,
};

enum hvc_ivc_event {
    HVC_IVC_UPDATE_MQ = 0,
    HVC_IVC_SEND_MSG,
    HVC_IVC_BROADCAST_MSG,
    HVC_IVC_INIT_KEEP_ALIVE, // 心跳包
    HVC_IVC_KEEP_ALIVE,      // 心跳包
    HVC_IVC_ACK,
    HVC_IVC_GET_TIME,
    HVC_IVC_SHARE_MEM,
    HVC_IVC_TEST_SEND = 0x10,
    HVC_IVC_GET_SHARED_MEM_IPA = 0x11,
    HVC_IVC_SEND_SHAREMEM_TEST_SPEED = 0x12,
    // HVC_IVC_INIT_RECEIVE_MSG,
};

enum hvc_mediated_event {
    HVC_MEDIATED_USER_NOTIFY = 0x20,
    HVC_MEDIATED_DEV_APPEND = 0x30,
    HVC_MEDIATED_DEV_NOTIFY,
    HVC_MEDIATED_DEV_INPUT_SEND = 0x40,
};

enum hvc_security_event {
    HVC_SECURITY_SET_CFG = 0,
    HVC_SECURITY_GET_CFG,
    HVC_SECURITY_GET_LOG,
    HVC_SECURITY_WATCH_DOG,
    HVC_SECURITY_GET_INFO,
    HVC_SECURITY_TEST,
    HVC_SECURITY_DEEP_TEST,
    HVC_SECURITY_RANDOM_TEST,
};

enum hvc_config_event {
    HVC_CONFIG_ADD_VM = 0,
    HVC_CONFIG_DELETE_VM,
    HVC_CONFIG_CPU,
    HVC_CONFIG_MEMORY_REGION,
    HVC_CONFIG_EMULATED_DEVICE,
    HVC_CONFIG_PASSTHROUGH_DEVICE_REGION,
    HVC_CONFIG_PASSTHROUGH_DEVICE_IRQS,
    HVC_CONFIG_PASSTHROUGH_DEVICE_STREAMS_IDS,
    HVC_CONFIG_DTB_DEVICE,
    HVC_CONFIG_UPLOAD_KERNEL_IMAGE,
    HVC_CONFIG_MEMORY_COLOR_BUDGET,
    HVC_CONFIG_UPLOAD_DEVICE_TREE,
};

enum ioctl_sys_event {
    IOCTL_SYS_GET_STATE = 0,
    IOCTL_SYS_RECEIVE_MSG,
    IOCTL_SYS_INIT_USR_PID,
    IOCTL_SYS_GET_SEND_IDX,
    IOCTL_SYS_GET_VMID,
    IOCTL_SYS_SET_KERNEL_IMG_NAME,
    IOCTL_SYS_GET_KERNEL_IMG_NAME,
    IOCTL_SYS_APPEND_MED_BLK = 0x10,
};

enum hvc_unilib_event {
    HVC_UNILIB_FS_INIT = 0,
    HVC_UNILIB_FS_OPEN = 1,
    HVC_UNILIB_FS_CLOSE = 2,
    HVC_UNILIB_FS_READ = 3,
    HVC_UNILIB_FS_WRITE = 4,
    HVC_UNILIB_FS_LSEEK = 5,
    HVC_UNILIB_FS_STAT = 6,
    HVC_UNILIB_FS_UNLINK = 7,
    HVC_UNILIB_FS_APPEND = 0x10,
    HVC_UNILIB_FS_FINISHED = 0x11,
};

enum hvc_shmem_event {
    HVC_SHMEM_INIT = 0,
    HVC_SHMEM_DELETE = 1,
};

enum security_test {
    ACC_2_N_3,
    ACF_1_N_1,
    ACF_1_N_2,
    ACF_1_N_3,
    ACC_2_N_1_A,
    ACC_2_N_1_B,
    ARP_1_N_6,
    ARP_1_N_2_1,
    ARP_1_N_2_2,
    ARP_1_N_2_3,
    ARP_1_N_2_4,
    ARP_1_N_1_1, // other mem
    ARP_1_N_1_2, // other dev
    ARP_1_N_1_3, // unknown addr
    ACC_2_N_4
};

// 用户程序结构体
struct write_arg {
    u64 vm_tgrt;
    u64 size;
    u64 addr;
    u64 idx;
    u64 fin;
};

struct send_arg {
    u64 vmid;
    u64 size;
    u64 page_num;
};

struct input_event {
    u16 type;
    u16 code;
    u32 value;
};

// VM shared memory ivc, not supported in Rust-shyper.
// extern void *BaseVAddrforSend;
// extern void *BaseVAddrforReceive;
// extern unsigned long BasePhysicalAddrforSend;
// extern unsigned long BasePhysicalAddrforReceive;
// extern unsigned long MaxSizeforSend;
// extern unsigned long MaxSizeforReceive;

u64 kva2ipa(u64 va);
u64 hvc_call(u64 x0, u64 x1, u64 x2, u64 x3, u64 x4, u64 x5, u64 x6,
             u64 hvc_mode) noinline;
bool handle_hvc(u64 hvc_fid, u64 event, u64 arg);

bool handle_hvc_sys(u64 event, u64 arg);
bool handle_hvc_vmm(u64 event, u64 arg);
bool handle_hvc_ivc(u64 event, u64 arg);
bool handle_hvc_network(u64 event, u64 arg);
bool handle_hvc_mediated(u64 event, u64 arg);
bool handle_hvc_security(u64 event, u64 arg);
bool handle_ioctl_sys(u64 event, u64 arg);
bool handle_hvc_config(u64 event, u64 arg);
bool handle_hvc_unilib(u64 event, u64 arg);
bool handle_hvc_shmem(u64 event, u64 arg);

#endif
